package com.nineclock.sign.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.alibaba.excel.write.style.column.AbstractColumnWidthStyleStrategy;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.nineclock.sign.mapper.SignPunchMapper;
import com.nineclock.sign.service.SignPunchService;
import com.nineclock.common.entity.PageResult;
import com.nineclock.common.entity.Result;
import com.nineclock.common.threadlocal.CurrentUserHolder;
import com.nineclock.common.utils.BeanHelper;
import com.nineclock.common.utils.DateTimeUtil;
import com.nineclock.sign.dto.SignDTO;
import com.nineclock.sign.dto.SignInfoDTO;
import com.nineclock.sign.dto.SignPCListDTO;
import com.nineclock.sign.pojo.SignInfo;
import com.nineclock.system.dto.SysCompanyUserDTO;
import com.nineclock.system.dto.SysDepartmentDTO;
import com.nineclock.system.feign.OrganizationFeign;
import com.nineclock.system.feign.SignFeign;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class SignPunchServiceImpl implements SignPunchService {
    @Autowired
    SignPunchMapper signPunchMapper;
    @Override
    public void export(String startTime, String endTime) throws IOException {
            //1. 获取时间段 内的考勤情况
           List<SignPCListDTO> signPCListDTOList = this.queryMembers(startTime, 1L,10L,endTime).getRows();


            //2. 获取响应对象，并设置 响应对象
            RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
            ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) requestAttributes;
            HttpServletResponse response = servletRequestAttributes.getResponse();
            response.setHeader("Content-disposition", "attachment;filename=Attendance.xlsx");
            response.setContentType("application/octet-stream;charset=UTF-8");
            response.setCharacterEncoding("utf-8");


            // *************easyExcel **********

            WriteCellStyle cellStyle = new WriteCellStyle();
            //表头和内容都是水平居中
            cellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);

            //设置字体
            WriteFont font = new WriteFont();
            font.setFontName("宋体");
            font.setFontHeightInPoints((short)12);
            cellStyle.setWriteFont(font);

            HorizontalCellStyleStrategy styleStrategy = new HorizontalCellStyleStrategy(cellStyle,cellStyle);

            EasyExcel.write(response.getOutputStream())
                    .head(handlerHead(signPCListDTOList))
                    .registerWriteHandler(styleStrategy)
                    .registerWriteHandler(new MyColumnStyle())
                    .sheet("测试数据")
                    .doWrite(handlerData(signPCListDTOList));

            // *************easyExcel **********

    }
    @Autowired
    SignFeign signFeign;
    public PageResult<SignPCListDTO> queryMembers(String startTime,Long page, Long pageSize, String endTime) {
        PageResult<SignPCListDTO> pcListDTOPageResult = new PageResult<>();
        //查询所有的员工数量
        PageResult<SysCompanyUserDTO> data = signFeign.queryCompanyMemberListByPage(page, pageSize).getData();
        // 获取 日期区间内时间列表
        List<Date> dateList = DateTimeUtil.getDatesBetweenTwoDate(startTime, endTime, "yyyy-MM-dd");
        //把日期列表 转换为 日期字符串列表
        List<String> dateStrList = dateList.stream().map(date -> {
            return DateTimeUtil.dateToStr(date, "yyyy-MM-dd");
        }).collect(Collectors.toList());

        pcListDTOPageResult.setTotal(data.getTotal());
        pcListDTOPageResult.setTotalPage(data.getTotalPage());
        //数据赋值
        List<SysCompanyUserDTO> sysCompanyUserDTOS = data.getRows();
        List<SignPCListDTO> pcListDTOS = sysCompanyUserDTOS.stream().map(
                row -> {
                    SignPCListDTO signPCListDTO = new SignPCListDTO();
                    signPCListDTO.setId(row.getId());
                    signPCListDTO.setPost(row.getPost());
                    signPCListDTO.setUsername(row.getUserName());
                    signPCListDTO.setWorkNumber(row.getWorkNumber());
                    SysDepartmentDTO sysDepartmentDTO = new SysDepartmentDTO();
                    sysDepartmentDTO.setId(row.getDepartmentId());
                    sysDepartmentDTO.setName(row.getDepartmentName());
                    signPCListDTO.setDepartment(sysDepartmentDTO);
                    return signPCListDTO;
                }
        ).collect(Collectors.toList());
        //查询每一个在指定时间段的员工的签到情况
        for (SignPCListDTO pcListDTO : pcListDTOS) {
            LambdaQueryWrapper<SignInfo> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(SignInfo::getCompanyId, CurrentUserHolder.get().getCompanyId())
                    .eq(SignInfo::getCompanyUserId, pcListDTO.getId())
                    .between(SignInfo::getCreateDate, startTime, endTime);
            //获取指定时间段内用户的签到记录
            List<SignInfo> signInfos = signPunchMapper.selectList(wrapper);

            //记录进行分组
            Map<String, List<SignInfo>> listMap =
                    signInfos.stream().collect(Collectors.groupingBy(SignInfo::getCreateDate));

            //存储员工每天的打卡情况
            List<SignInfoDTO> signInfoDTOS = new ArrayList<>();
            //循环时间列表
            for (String dataStr : dateStrList) {
                SignInfoDTO signInfoDTO = new SignInfoDTO();
                //分组获得每天的签到信息
                List<SignInfo> signInfos1 = listMap.get(dataStr);
                //如果没有签到信息,就是0
                if (CollectionUtil.isEmpty(signInfos1)) {
                    signInfoDTO.setSignCount(0);
                } else {
                    signInfoDTO.setSignCount(signInfos1.size());
                }
                signInfoDTO.setSignDate(dataStr);  //设置日期
                signInfoDTOS.add(signInfoDTO);
            }
            pcListDTO.setSigns(signInfoDTOS);
        }
        pcListDTOPageResult.setRows(pcListDTOS);
        return pcListDTOPageResult;
    }


    @Override
    public String queryDayCount() {
        Long companyUserId = CurrentUserHolder.get().getCompanyUserId();
        //获取当前日期字符串
        String dateStr = DateTimeUtil.dateToStr(new Date(), "yyyy-MM-dd");
        Long companyId = CurrentUserHolder.get().getCompanyId();
        LambdaQueryWrapper<SignInfo> wrapper=new LambdaQueryWrapper<>();
        wrapper.eq(SignInfo::getCompanyId,companyId)
                .eq(SignInfo::getCompanyUserId,companyUserId)
                .eq(SignInfo::getCreateDate,dateStr);
        List<SignInfo> signInfos = signPunchMapper.selectList(wrapper);

        String dayCount = signInfos.size()+"";
        return dayCount;

    }

    //操作数据
    private List<List<String>> handlerData(List<SignPCListDTO> signPCListDTOList) {
        List<List<String>> data = new ArrayList<>();
        //循环 每一个 员工
        for (SignPCListDTO signPCListDTO : signPCListDTOList) {
            //new一个集合
            List<String> list=new ArrayList<>();
            //添加员工的姓名
            list.add(signPCListDTO.getUsername());
            //添加员工的工号
            list.add(signPCListDTO.getWorkNumber());
            //添加员工的部门名称
            list.add(signPCListDTO.getDepartment().getName());
            //添加员工职位
            list.add(signPCListDTO.getPost());
            //将考勤状况添加进去
            List<SignInfoDTO> signs = signPCListDTO.getSigns();
            for (SignInfoDTO sign : signs) {
                list.add(String.valueOf(sign.getSignCount()));
            }
            data.add(list);
        }

        return data;
    }

    /**
     * 操作表头
     * @return
     */
    private List<List<String>> handlerHead(List<SignPCListDTO> signPCListDTOList) {
        List<List<String>> head = new ArrayList<>();
        head.add(Arrays.asList("姓名"));
        head.add(Arrays.asList("工号"));
        head.add(Arrays.asList("部门"));
        head.add(Arrays.asList("职位"));
        //获取集合中的第一个对象
        //获取了第一个员工的每天打卡情况 对应 日期
        SignPCListDTO listDTO = signPCListDTOList.get(0);
        List<SignInfoDTO> signs = listDTO.getSigns();
        for (SignInfoDTO sign : signs) {
            head.add(Arrays.asList(sign.getSignDate()));
        }

        return head;
    }
    class MyColumnStyle extends AbstractColumnWidthStyleStrategy {

        @Override
        protected void setColumnWidth(WriteSheetHolder writeSheetHolder,
                                      List<CellData> cellDataList,
                                      Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
            writeSheetHolder.getSheet().setColumnWidth(cell.getColumnIndex(), 4500);
        }
    }
}
